/*
** communication.c for zappy in /home/guidet_m/TECK2/projets/zappy/server_zappy
** 
** Made by michael guidet
** Login   <guidet_m@epitech.net>
** 
** Started on  Tue Jul  5 10:18:21 2011 michael guidet
** Last update Mon Jul 11 17:52:37 2011 guillaume kizilian
*/

#include "server.h"

void	client_read(t_fd *cs, t_env *e)
{
  char	*tmp;

  if (cs->type == DEAD)
    return ;
  tmp = clean_string_list(&cs->receive_list);
  memset(cs->buf_read, 0, BUF_SIZE + 1);
  if (recv(cs->fd, cs->buf_read, BUF_SIZE, 0) <= 0)
    {
      printf("%sClient disconnected%s\n", RED, DEFAUT);
      cs->type = cs->type == AI ? DEAD : DECO;
      return ;
    }
  if (cs->pl)
    printf("%sMessage received from %d %s : %s%s", BLUE,
	   cs->pl->id, cs->pl->team, cs->buf_read, DEFAUT);
  else if (cs->type == GRAPH)
    printf("%sMessage received from graphic client : %s%s", BLUE,
	   cs->buf_read, DEFAUT);
  else
    printf("%sMessage received : %s%s", BLUE, cs->buf_read, DEFAUT);
  parse_action(cs, e, tmp);
}

void	client_write(t_fd *cs, t_env *e)
{
  char	*tmp;

  if (cs->type == DEAD)
    return ;
  tmp = clean_string_list(&cs->send_list);
  if (cs->pl)
    printf("%sMessage send to %d %s : %s%s", GREEN, cs->pl->id,
	   cs->pl->team, tmp, DEFAUT);
  else if (cs->type == GRAPH)
    printf("%sMessage send to graphic client : %s%s", GREEN, tmp, DEFAUT);
  else
    printf("%sMessage send : %s%s", GREEN, tmp, DEFAUT);
  x_int(-1, send(cs->fd, tmp, strlen(tmp), 0), "send");
  free(tmp);
  e = e;
}

void			server_accept(t_env *e, int s)
{
  int			cs;
  int			i;
  t_fd			*new_elem;
  struct sockaddr_in	csin;
  socklen_t		csin_len;

  csin_len = sizeof(csin);
  cs = x_int(-1, accept(s, (struct sockaddr*)&csin, &csin_len), "accept");
  printf("New client #%d from %s:%d\n", cs,
	 inet_ntoa(csin.sin_addr), ntohs(csin.sin_port));
  new_elem = x_null(NULL, malloc(sizeof(*new_elem)), "malloc");
  new_elem->receive_list = NULL;
  new_elem->send_list = NULL;
  new_elem->fd = cs;
  new_elem->type = UNKNOW;
  new_elem->wait = -1;
  new_elem->idaction = -1;
  new_elem->pl = NULL;
  memset(new_elem->buf_read, 0, BUF_SIZE + 1);
  memset(new_elem->buf_write, 0, BUF_SIZE + 1);
  add_string_to_list(&new_elem->send_list, "BIENVENUE\n");
  new_elem->next = e->fd;
  e->fd = new_elem;
  for (i = 0; i < 10; i++)
    new_elem->action_list[i] = NULL;
}

void	refresh_fd(t_env *e)
{
  t_fd	*tmp;

  FD_ZERO(&e->fd_read);
  FD_ZERO(&e->fd_write);
  for (e->max = 0, tmp = e->fd; tmp; tmp = tmp->next)
    {
      FD_SET(tmp->fd, &e->fd_read);
      if (tmp->send_list != NULL)
	FD_SET(tmp->fd, &e->fd_write);
      e->max = (e->max > tmp->fd) ? e->max : tmp->fd;
    }
}

void			check_fd(t_env *e)
{
  int			res;
  t_fd			*tmp;
  struct timeval	timeout;

  int_to_timeval(&timeout, calc_mintime(e));
  x_int(-1, gettimeofday(&e->elapsed, NULL), "gettimeofday");
  res = x_int(-1, select(e->max + 1, &e->fd_read, &e->fd_write, NULL,
		      (timeout.tv_sec || timeout.tv_usec)? &timeout : NULL), "select");
  calc_elapsed(&e->elapsed);
  for (tmp = e->fd; tmp && res > 0; tmp = tmp->next)
    {
      if (FD_ISSET(tmp->fd, &e->fd_read))
	{
	  if (tmp->type == SERV)
	    server_accept(e, tmp->fd);
	  else
	    client_read(tmp, e);
	}
      if (FD_ISSET(tmp->fd, &e->fd_write))
	client_write(tmp, e);
      if (FD_ISSET(tmp->fd, &e->fd_read) || FD_ISSET(tmp->fd, &e->fd_write))
	res--;
    }
}

